/* Certificate creation for TPM EK.
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/pem.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/x509v3.h>
#include <trousers/tss.h>
#include <trousers/trousers.h>
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <time.h>
#endif
//#define TPM_GEO "XEN_GEO_BANGLORE
//
char* TPM_GEO = NULL;

void log_msg(char* file,int line,char *msg, ...);

#define SHA_DIGEST_LENGTH 20

#define TPM_NV_INDEX_GEO    ((UINT32)0x00000005)


/* Generate a pu key in PEM format
 *openssl rsa -in ssh_host_rsa_key -pubout > /etc/tpm/xen.pub
 */


#define BSIZE	128
#define CKERR	if (result != TSS_SUCCESS) goto error

/* Definitions from section 7 of
 * TCG PC Client Specific Implementation Specification
 * For Conventional BIOS
 */
#define TCG_TAG_PCCLIENT_STORED_CERT		0x1001
#define TCG_TAG_PCCLIENT_FULL_CERT		0x1002
#define TCG_TAG_PCCLIENT_PART_SMALL_CERT	0x1003
#define TCG_FULL_CERT				0
#define TCG_PARTIAL_SMALL_CERT			1


/*
 *Function tries to read a TPM
 *certificate from NV_RAM 
 * return 0 on success
 * 
 * */

FILE *log_filp;

/* Read the TPM EK
 * TODO : generate one and insert if does not exist
 * 
 */

unsigned char tpm_key[SHA_DIGEST_LENGTH] ;
unsigned char key_hash[] = "3beac9388f9b489d50bb01e2ff0fa2aaa9ee1d73" ;

static char get_val(char c)
{
    if (isdigit(c))
        return  ( c - '0');
    else if (isupper(c))
        return  (c - 'A' + 10);
    else if (islower(c))
        return (c - 'a' + 10);
    return -1;
}


static int get_key_bytes(unsigned char * md, unsigned char * buf)
{
    int i;
    char t1;
    char t2;
    for (i = 0;i < SHA_DIGEST_LENGTH; i++) {
        t1 = get_val(buf[i*2]);
        t2 = get_val(buf[i*2+1]);
        if( t1 < 0 || t2 < 0) {
            return 1;
        }
        md[i] = (t1 << 4) + t2;
    }
    return 0;
}

#define EVENT_DATA_SIZE 32

extend_pcr()
{
    TSS_HCONTEXT  context ;
    TSS_HTPM tpm ;
	TSS_HPOLICY		policy_tpm;
    BYTE        *pcrValue;
    UINT32      ulPcrValueLength, subCap, numPcrs, i, j;
    BYTE        *NewPcrValue, *rgbNumPcrs;
    TSS_RESULT  result;
    BYTE        event_data[EVENT_DATA_SIZE];

    result = Tspi_Context_Create(&context);CKERR;
	result = Tspi_Context_Connect(context, NULL);CKERR;
	result = Tspi_Context_GetTpmObject(context, &tpm);CKERR;

	result = Tspi_Context_CreateObject(context, TSS_OBJECT_TYPE_POLICY, 
                TSS_POLICY_USAGE, &policy_tpm);CKERR;

    result = Tspi_Policy_SetSecret((policy_tpm), TSS_SECRET_MODE_SHA1,
            (UINT32)(sizeof(tpm_key)), (BYTE*)tpm_key);CKERR;

    result = Tspi_Policy_AssignToObject(policy_tpm, tpm);CKERR;

    TSS_PCR_EVENT event;
    memset(&event, 0, sizeof(TSS_PCR_EVENT));
    event.rgbEvent = event_data;
    event.ulEventLength = EVENT_DATA_SIZE;
    event.ulPcrValueLength = 20;

    result = Tspi_TPM_GetRandom(tpm, 20, &pcrValue);CKERR;
    event.rgbPcrValue = pcrValue;
    numPcrs = 24;

    for (i = 0; i < numPcrs; i++) {
        memset(&event_data, i, EVENT_DATA_SIZE);
        event.ulPcrIndex = i;

        result = Tspi_TPM_PcrExtend(tpm, i, 20, pcrValue, &event,
                &ulPcrValueLength, &NewPcrValue);CKERR;
    }
	
    result = Tspi_Context_CloseObject(context, policy_tpm); CKERR;
	result = Tspi_Context_FreeMemory(context, NULL);
	result = Tspi_Context_Close(context);CKERR;
    fprintf(stdout,"%s\n","Success in pcr extend");
    return; 
    error:
        fprintf(stdout, "%s %s \n","Error in extend_pcr ",Trspi_Error_String(result));
	    return;
}

int main(int argc, char **av)
{
   extend_pcr(); 
    return(0);
}

